# include <bits/stdc++.h>
# define ll long long
# define MAXN 100023
using namespace std;
int n, m, r, p, a[MAXN], aid[MAXN];

inline ll get_num() {
	ll k = 0, f = 1;
	char c = getchar();
	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
	for(; isdigit(c); c = getchar()) k = k * 10 + c - '0';
	return k * f;
}

struct edge {
	int fr, to, ne;
	edge(){;}
	edge(int fr_, int to_, int ne_) {
		fr = fr_, to = to_, ne = ne_;
	}
}e[MAXN];

int head[MAXN], cnt;

inline void add_edge(int fr, int to) {
	e[++cnt] = edge(fr, to, head[fr]), head[fr] = cnt;
	e[++cnt] = edge(to, fr, head[to]), head[to] = cnt;
}

int sz[MAXN], fa[MAXN], de[MAXN], hs[MAXN];

void dfs1(int x, int f) {
	fa[x] = f;
	sz[x] = 1;
	de[x] = de[f] + 1;
	for(int i = head[x]; i; i = e[i].ne) {
		int y = e[i].to;
		if(y == f) continue;
		dfs1(y, x);
		sz[x] += sz[y];
		if(sz[y] > sz[hs[x]]) {
			hs[x] = y;
		}
	}
}

int ids = 0;
int id[MAXN], tp[MAXN];

void dfs2(int x, int t) {
	id[x] = ++ids;
	aid[id[x]] = x;
	tp[x] = t;
	if(!hs[x]) return;
	dfs2(hs[x], t);
	for(int i = head[x]; i; i = e[i].ne) {
		int y = e[i].to;
		if(y == fa[x] || y == hs[x]) continue;
		dfs2(y, y);
	}
}

struct segtree {
# define mid ((l + r) >> 1)
# define lc (x << 1)
# define rc (x << 1 | 1)
	ll sm[MAXN << 1], lz[MAXN << 1];
	segtree(){
		memset(sm, 0, sizeof(sm));
		memset(lz, 0, sizeof(lz));
	}
	void build(int x, int l, int r) {
		if(l == r) {
			sm[x] = a[aid[l]];
			return;
		} else {
			build(lc, l, mid);
			build(rc, mid + 1, r);
			sm[x] = sm[lc] + sm[rc];
//			printf("%d  l %d  r %d  sm %d\n", x, l, r, sm[x]);
			return;
			
		}
	}
	inline void push_down(int x, int l, int r) {
		if(!lz[x]) return;
		lz[lc] += lz[x];
		sm[lc] += lz[x] * (mid - l + 1);
		lz[rc] += lz[x];
		sm[rc] += lz[x] * (r - mid);
		lz[x] = 0;
		return;
	}
	void update(int x, int l, int r, int s, int t, int k) {
		if(l == s && r == t) {
			lz[x] += k;
			sm[x] += k * (r - l + 1);
			push_down(x, l, r);
			return;
		}
		push_down(x, l, r);
		if(t <= mid) update(lc, l, mid, s, t, k);
		else if(s > mid) update(rc, mid + 1, r, s, t, k);
		else {
			update(lc, l, mid, s, mid, k);
			update(rc, mid + 1, r, mid + 1, t, k);
		}
		sm[x] = sm[lc] + sm[rc];
		push_down(x, l, r);
	}
	ll find_sum(int x, int l, int r, int s, int t) {
		if(l == s && r == t) {
			push_down(x, l, r);
			return sm[x];
		}
		push_down(x, l, r);
		if(t <= mid) return find_sum(lc, l, mid, s, t);
		else if(s > mid) return find_sum(rc, mid + 1, r, s, t);
		else {
			return (find_sum(lc, l, mid, s, mid) + find_sum(rc, mid + 1, r, mid + 1, t)) % p;
		}
	}
	inline ll get_sum(int a, int b) {
		ll sum = 0;
		int ta = tp[a], tb =tp[b];
		while(ta != tb) {
			if(de[ta] < de[tb]) { // 保证ta在tb下面
				swap(ta, tb);
				swap(a, b);
			}
			sum += find_sum(1, 1, ids, id[ta], id[a]);
			sum %= p;
			a = fa[ta];
			ta = tp[a];
		}
		if(de[a] > de[b]) swap(a, b);//a在下面
		sum += find_sum(1, 1, ids, id[a], id[b]);
		return sum % p;
	}
	inline void change(int a, int b, int k) {
		int ta = tp[a], tb = tp[b];
		while(ta != tb) {
			if(de[ta] < de[tb]) { // 保证ta在tb下面
				swap(ta, tb);
				swap(a, b);
			}
			update(1, 1, ids, id[ta], id[a], k);
			a = fa[ta];
			ta = tp[a];
		}
		if(de[a] > de[b]) swap(a, b);//a在下面
		update(1, 1, ids, id[a], id[b], k);
	}
  inline void change_root(int x, int z) {
    update(1, 1, ids, id[x], id[x] + sz[x] - 1, z);
  }
  inline ll sum_root(int x) {
    return find_sum(1, 1, ids, id[x], id[x] + sz[x] - 1) % p;
  }
}T;
int main() {
//	freopen("in.txt", "r", stdin);
	n = get_num();
	m = get_num();
	r = get_num();
	p = get_num();

	for(int i = 1; i <= n; i++) {
		a[i] = get_num();
	}
	
	for(int i = 1; i < n; i++) {
		int u = get_num();
		int v = get_num();
		add_edge(u, v);
	}
	
	dfs1(r, 0);
	dfs2(r, r);
	T.build(1, 1, ids);
	while(m--) {
		int type = get_num();
		if(type == 1) {
			int x = get_num();
			int y = get_num();
			int z = get_num();
			T.change(x, y, z);
		} else if(type == 2) {
			int x = get_num();
			int y = get_num();
			printf("%lld\n", T.get_sum(x, y));
		} else if(type == 3) {
     		int x = get_num();
     		int z = get_num();
    		T.change_root(x, z);
    	} else if(type == 4) {
      		int x = get_num();
     	 	printf("%lld\n", T.sum_root(x));
    	}
	}
  return 0;
}
